//  -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	Smart.Common
//  File name:	SaveMe.cs
//  Developer:	Solomatov Igor
//  Created:	15.04.2012
// 
//  -------------------- iSharePoint -------------------- //

using System.Collections.Generic;
using System.Diagnostics;
using System.Web.UI;

namespace Smart
{
	[DebuggerStepThrough]
	public class SaveMe<TKeyType, TValueType>
	{
		public enum CacheMode
		{
			AllAtOnce,
			ByItem
		}

		public StateBag ViewState;
		public string ViewStateKey;

		public Dictionary<TKeyType, TValueType> Cache;

		public FillAllHandler<TKeyType, TValueType> FillAllMethod;
		public FillItemHandler<TKeyType, TValueType> FillItemMethod;

		public CacheMode Mode = CacheMode.AllAtOnce;

		public SaveMe(StateBag viewState, string viewStateKey, FillAllHandler<TKeyType, TValueType> fillMethod)
		{
			ViewState = viewState;
			ViewStateKey = viewStateKey;
			FillAllMethod = fillMethod;
			Mode = CacheMode.AllAtOnce;
		}

		public SaveMe(StateBag viewState, string viewStateKey, FillItemHandler<TKeyType, TValueType> fillMethod)
		{
			ViewState = viewState;
			ViewStateKey = viewStateKey;
			FillItemMethod = fillMethod;
			Mode = CacheMode.ByItem;
		}

		public SaveMe(StateBag viewState, string viewStateKey)
		{
			ViewState = viewState;
			ViewStateKey = viewStateKey;
			FillAllMethod = () => new Dictionary<TKeyType, TValueType>();
			Mode = CacheMode.AllAtOnce;
		}

		public virtual void Set(Dictionary<TKeyType, TValueType> value)
		{
			ViewState[ViewStateKey] = Cache = value;
		}

		public virtual Dictionary<TKeyType, TValueType> Get()
		{
			if (Cache == null)
			{
				Cache = ViewState[ViewStateKey] as Dictionary<TKeyType, TValueType>;

				if (Cache == null)
				{
					switch (Mode)
					{
						case CacheMode.AllAtOnce:
							ViewState[ViewStateKey] = Cache = FillAllMethod();
							break;

						case CacheMode.ByItem:
							ViewState[ViewStateKey] = Cache = new Dictionary<TKeyType, TValueType>();
							break;
					}
				}
			}

			return Cache;
		}

		public virtual TValueType this[TKeyType key]
		{
			get
			{
				if (Cache == null)
				{
					Cache = ViewState[ViewStateKey] as Dictionary<TKeyType, TValueType>;

					if (Cache == null)
					{
						switch (Mode)
						{
							case CacheMode.AllAtOnce:
								ViewState[ViewStateKey] = Cache = FillAllMethod();
								break;

							case CacheMode.ByItem:
								ViewState[ViewStateKey] = Cache = new Dictionary<TKeyType, TValueType>();
								break;
						}
					}
				}

				if (Cache == null)
					return default(TValueType);

				TValueType value;

				if (!Cache.TryGetValue(key, out value))
				{
					if (Mode == CacheMode.ByItem)
					{
						Cache[key] = value = FillItemMethod(key);
					}
					else
					{
						value = default(TValueType);
					}
				}

				return value;
			}
			set
			{
				if (Cache == null)
				{
					Cache = ViewState[ViewStateKey] as Dictionary<TKeyType, TValueType>;

					if (Cache == null)
						ViewState[ViewStateKey] = Cache = new Dictionary<TKeyType, TValueType>();
				}

				if (Cache == null)
					return;

				Cache[key] = value;
			}
		}
	}

	[DebuggerStepThrough]
	public class SaveMe<TValueType>
	{
		public StateBag ViewState;
		public string ViewStateKey;

		public SaveMe(StateBag viewState, string viewStateKey)
		{
			ViewState = viewState;
			ViewStateKey = viewStateKey;
		}

		protected bool Inited;
		protected TValueType InternalValue;
		protected TValueType InternalDefault;

		public void EnsureValue()
		{
			if (Inited) return;

			Inited = true;

			var vsv = ViewState[ViewStateKey];

			if (vsv is TValueType)
				InternalValue = (TValueType)vsv;
			else
				InternalValue = InternalDefault;
		}

		public TValueType Value
		{
			get { EnsureValue(); return InternalValue; }
			set { ViewState[ViewStateKey] = InternalValue = value; }
		}
	}
}